package java.lang;

import java.util.Random;

public final class Math {

	private Math() {
	}

	private static Random rand;

	public static final double E = 2.718281828459045;
	public static final double PI = 3.141592653589793;

	/**
	 * Take the absolute value of the argument. (Absolute value means make it
	 * positive.)
	 * <P>
	 * 
	 * Note that the the largest negative value (Integer.MIN_VALUE) cannot be
	 * made positive. In this case, because of the rules of negation in a
	 * computer, MIN_VALUE is what will be returned. This is a <em>negative</em>
	 * value. You have been warned.
	 * 
	 * @param i
	 *            the number to take the absolute value of
	 * @return the absolute value
	 * @see Integer#MIN_VALUE
	 */
	public static int abs(int i) {
		return (i < 0) ? -i : i;
	}

	/**
	 * Take the absolute value of the argument. (Absolute value means make it
	 * positive.)
	 * <P>
	 * 
	 * Note that the the largest negative value (Long.MIN_VALUE) cannot be made
	 * positive. In this case, because of the rules of negation in a computer,
	 * MIN_VALUE is what will be returned. This is a <em>negative</em> value.
	 * You have been warned.
	 * 
	 * @param l
	 *            the number to take the absolute value of
	 * @return the absolute value
	 * @see Long#MIN_VALUE
	 */
	public static long abs(long l) {
		return (l < 0) ? -l : l;
	}

	/**
	 * Take the absolute value of the argument. (Absolute value means make it
	 * positive.)
	 * <P>
	 * 
	 * This is equivalent, but faster than, calling
	 * <code>Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))</code>.
	 * 
	 * @param f
	 *            the number to take the absolute value of
	 * @return the absolute value
	 */
	public static float abs(float f) {
		return (f <= 0) ? 0 - f : f;
	}

	/**
	 * Take the absolute value of the argument. (Absolute value means make it
	 * positive.)
	 * 
	 * This is equivalent, but faster than, calling
	 * <code>Double.longBitsToDouble(Double.doubleToLongBits(a)
	 *       &lt;&lt; 1) &gt;&gt;&gt; 1);</code>.
	 * 
	 * @param d
	 *            the number to take the absolute value of
	 * @return the absolute value
	 */
	public static double abs(double d) {
		return (d <= 0) ? 0 - d : d;
	}

	/**
	 * Return whichever argument is smaller.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the smaller of the two numbers
	 */
	public static int min(int a, int b) {
		return (a < b) ? a : b;
	}

	/**
	 * Return whichever argument is smaller.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the smaller of the two numbers
	 */
	public static long min(long a, long b) {
		return (a < b) ? a : b;
	}

	/**
	 * Return whichever argument is smaller. If either argument is NaN, the
	 * result is NaN, and when comparing 0 and -0, -0 is always smaller.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the smaller of the two numbers
	 */
	public static float min(float a, float b) {
		// this check for NaN, from JLS 15.21.1, saves a method call
		if (a != a)
			return a;
		// no need to check if b is NaN; < will work correctly
		// recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
		if (a == 0 && b == 0)
			return -(-a - b);
		return (a < b) ? a : b;
	}

	/**
	 * Return whichever argument is smaller. If either argument is NaN, the
	 * result is NaN, and when comparing 0 and -0, -0 is always smaller.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the smaller of the two numbers
	 */
	public static double min(double a, double b) {
		// this check for NaN, from JLS 15.21.1, saves a method call
		if (a != a)
			return a;
		// no need to check if b is NaN; < will work correctly
		// recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
		if (a == 0 && b == 0)
			return -(-a - b);
		return (a < b) ? a : b;
	}

	/**
	 * Return whichever argument is larger.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the larger of the two numbers
	 */
	public static int max(int a, int b) {
		return (a > b) ? a : b;
	}

	/**
	 * Return whichever argument is larger.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the larger of the two numbers
	 */
	public static long max(long a, long b) {
		return (a > b) ? a : b;
	}

	/**
	 * Return whichever argument is larger. If either argument is NaN, the
	 * result is NaN, and when comparing 0 and -0, 0 is always larger.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the larger of the two numbers
	 */
	public static float max(float a, float b) {
		// this check for NaN, from JLS 15.21.1, saves a method call
		if (a != a)
			return a;
		// no need to check if b is NaN; > will work correctly
		// recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
		if (a == 0 && b == 0)
			return a - -b;
		return (a > b) ? a : b;
	}

	/**
	 * Return whichever argument is larger. If either argument is NaN, the
	 * result is NaN, and when comparing 0 and -0, 0 is always larger.
	 * 
	 * @param a
	 *            the first number
	 * @param b
	 *            a second number
	 * @return the larger of the two numbers
	 */
	public static double max(double a, double b) {
		// this check for NaN, from JLS 15.21.1, saves a method call
		if (a != a)
			return a;
		// no need to check if b is NaN; > will work correctly
		// recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
		if (a == 0 && b == 0)
			return a - -b;
		return (a > b) ? a : b;
	}

	/**
	 * The trigonometric function <em>sin</em>. The sine of NaN or infinity is
	 * NaN, and the sine of 0 retains its sign. This is accurate within 1 ulp,
	 * and is semi-monotonic.
	 * 
	 * @param a
	 *            the angle (in radians)
	 * @return sin(a)
	 */
	public static double sin(double a) {
		return VMNumber.sin(a);
	}

	/**
	 * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is
	 * NaN. This is accurate within 1 ulp, and is semi-monotonic.
	 * 
	 * @param a
	 *            the angle (in radians)
	 * @return cos(a)
	 */
	public static double cos(double a) {
		return VMNumber.cos(a);
	}

	/**
	 * The trigonometric function <em>tan</em>. The tangent of NaN or infinity
	 * is NaN, and the tangent of 0 retains its sign. This is accurate within 1
	 * ulp, and is semi-monotonic.
	 * 
	 * @param a
	 *            the angle (in radians)
	 * @return tan(a)
	 */
	public static double tan(double a) {
		return VMNumber.tan(a);
	}

	/**
	 * The trigonometric function <em>arcsin</em>. The range of angles returned
	 * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN or
	 * its absolute value is beyond 1, the result is NaN; and the arcsine of 0
	 * retains its sign. This is accurate within 1 ulp, and is semi-monotonic.
	 * 
	 * @param a
	 *            the sin to turn back into an angle
	 * @return arcsin(a)
	 */
	public static double asin(double a) {
		return VMNumber.asin(a);
	}

	/**
	 * The trigonometric function <em>arccos</em>. The range of angles returned
	 * is 0 to pi radians (0 to 180 degrees). If the argument is NaN or its
	 * absolute value is beyond 1, the result is NaN. This is accurate within 1
	 * ulp, and is semi-monotonic.
	 * 
	 * @param a
	 *            the cos to turn back into an angle
	 * @return arccos(a)
	 */
	public static double acos(double a) {
		return VMNumber.acos(a);
	}

	/**
	 * The trigonometric function <em>arcsin</em>. The range of angles returned
	 * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN, the
	 * result is NaN; and the arctangent of 0 retains its sign. This is accurate
	 * within 1 ulp, and is semi-monotonic.
	 * 
	 * @param a
	 *            the tan to turn back into an angle
	 * @return arcsin(a)
	 * @see #atan2(double, double)
	 */
	public static double atan(double a) {
		return VMNumber.atan(a);
	}

	/**
	 * A special version of the trigonometric function <em>arctan</em>, for
	 * converting rectangular coordinates <em>(x, y)</em> to polar
	 * <em>(r, theta)</em>. This computes the arctangent of x/y in the range of
	 * -pi to pi radians (-180 to 180 degrees). Special cases:
	 * <ul>
	 * <li>If either argument is NaN, the result is NaN.</li>
	 * <li>If the first argument is positive zero and the second argument is
	 * positive, or the first argument is positive and finite and the second
	 * argument is positive infinity, then the result is positive zero.</li>
	 * <li>If the first argument is negative zero and the second argument is
	 * positive, or the first argument is negative and finite and the second
	 * argument is positive infinity, then the result is negative zero.</li>
	 * <li>If the first argument is positive zero and the second argument is
	 * negative, or the first argument is positive and finite and the second
	 * argument is negative infinity, then the result is the double value
	 * closest to pi.</li>
	 * <li>If the first argument is negative zero and the second argument is
	 * negative, or the first argument is negative and finite and the second
	 * argument is negative infinity, then the result is the double value
	 * closest to -pi.</li>
	 * <li>If the first argument is positive and the second argument is positive
	 * zero or negative zero, or the first argument is positive infinity and the
	 * second argument is finite, then the result is the double value closest to
	 * pi/2.</li>
	 * <li>If the first argument is negative and the second argument is positive
	 * zero or negative zero, or the first argument is negative infinity and the
	 * second argument is finite, then the result is the double value closest to
	 * -pi/2.</li>
	 * <li>If both arguments are positive infinity, then the result is the
	 * double value closest to pi/4.</li>
	 * <li>If the first argument is positive infinity and the second argument is
	 * negative infinity, then the result is the double value closest to 3*pi/4.
	 * </li>
	 * <li>If the first argument is negative infinity and the second argument is
	 * positive infinity, then the result is the double value closest to -pi/4.</li>
	 * <li>If both arguments are negative infinity, then the result is the
	 * double value closest to -3*pi/4.</li>
	 * 
	 * </ul>
	 * <p>
	 * This is accurate within 2 ulps, and is semi-monotonic. To get r, use
	 * sqrt(x*x+y*y).
	 * 
	 * @param y
	 *            the y position
	 * @param x
	 *            the x position
	 * @return <em>theta</em> in the conversion of (x, y) to (r, theta)
	 * @see #atan(double)
	 */
	public static double atan2(double y, double x) {
		return VMNumber.atan2(y, x);
	}

	/**
	 * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the
	 * argument is NaN, the result is NaN; if the argument is positive infinity,
	 * the result is positive infinity; and if the argument is negative
	 * infinity, the result is positive zero. This is accurate within 1 ulp, and
	 * is semi-monotonic.
	 * 
	 * @param a
	 *            the number to raise to the power
	 * @return the number raised to the power of <em>e</em>
	 * @see #log(double)
	 * @see #pow(double, double)
	 */
	public static double exp(double a) {
		return VMNumber.exp(a);
	}

	/**
	 * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the
	 * argument is NaN or negative, the result is NaN; if the argument is
	 * positive infinity, the result is positive infinity; and if the argument
	 * is either zero, the result is negative infinity. This is accurate within
	 * 1 ulp, and is semi-monotonic.
	 * 
	 * <p>
	 * Note that the way to get log<sub>b</sub>(a) is to do this:
	 * <code>ln(a) / ln(b)</code>.
	 * 
	 * @param a
	 *            the number to take the natural log of
	 * @return the natural log of <code>a</code>
	 * @see #exp(double)
	 */
	public static double log(double a) {
		return VMNumber.log(a);
	}

	/**
	 * Take a square root. If the argument is NaN or negative, the result is
	 * NaN; if the argument is positive infinity, the result is positive
	 * infinity; and if the result is either zero, the result is the same. This
	 * is accurate within the limits of doubles.
	 * 
	 * <p>
	 * For a cube root, use <code>cbrt</code>. For other roots, use
	 * <code>pow(a, 1 / rootNumber)</code>.
	 * </p>
	 * 
	 * @param a
	 *            the numeric argument
	 * @return the square root of the argument
	 * @see #cbrt(double)
	 * @see #pow(double, double)
	 */
	public static double sqrt(double a) {
		return VMNumber.sqrt(a);
	}

	/**
	 * Raise a number to a power. Special cases:
	 * <ul>
	 * <li>If the second argument is positive or negative zero, then the result
	 * is 1.0.</li>
	 * <li>If the second argument is 1.0, then the result is the same as the
	 * first argument.</li>
	 * <li>If the second argument is NaN, then the result is NaN.</li>
	 * <li>If the first argument is NaN and the second argument is nonzero, then
	 * the result is NaN.</li>
	 * <li>If the absolute value of the first argument is greater than 1 and the
	 * second argument is positive infinity, or the absolute value of the first
	 * argument is less than 1 and the second argument is negative infinity,
	 * then the result is positive infinity.</li>
	 * <li>If the absolute value of the first argument is greater than 1 and the
	 * second argument is negative infinity, or the absolute value of the first
	 * argument is less than 1 and the second argument is positive infinity,
	 * then the result is positive zero.</li>
	 * <li>If the absolute value of the first argument equals 1 and the second
	 * argument is infinite, then the result is NaN.</li>
	 * <li>If the first argument is positive zero and the second argument is
	 * greater than zero, or the first argument is positive infinity and the
	 * second argument is less than zero, then the result is positive zero.</li>
	 * <li>If the first argument is positive zero and the second argument is
	 * less than zero, or the first argument is positive infinity and the second
	 * argument is greater than zero, then the result is positive infinity.</li>
	 * <li>If the first argument is negative zero and the second argument is
	 * greater than zero but not a finite odd integer, or the first argument is
	 * negative infinity and the second argument is less than zero but not a
	 * finite odd integer, then the result is positive zero.</li>
	 * <li>If the first argument is negative zero and the second argument is a
	 * positive finite odd integer, or the first argument is negative infinity
	 * and the second argument is a negative finite odd integer, then the result
	 * is negative zero.</li>
	 * <li>If the first argument is negative zero and the second argument is
	 * less than zero but not a finite odd integer, or the first argument is
	 * negative infinity and the second argument is greater than zero but not a
	 * finite odd integer, then the result is positive infinity.</li>
	 * <li>If the first argument is negative zero and the second argument is a
	 * negative finite odd integer, or the first argument is negative infinity
	 * and the second argument is a positive finite odd integer, then the result
	 * is negative infinity.</li>
	 * <li>If the first argument is less than zero and the second argument is a
	 * finite even integer, then the result is equal to the result of raising
	 * the absolute value of the first argument to the power of the second
	 * argument.</li>
	 * <li>If the first argument is less than zero and the second argument is a
	 * finite odd integer, then the result is equal to the negative of the
	 * result of raising the absolute value of the first argument to the power
	 * of the second argument.</li>
	 * <li>If the first argument is finite and less than zero and the second
	 * argument is finite and not an integer, then the result is NaN.</li>
	 * <li>If both arguments are integers, then the result is exactly equal to
	 * the mathematical result of raising the first argument to the power of the
	 * second argument if that result can in fact be represented exactly as a
	 * double value.</li>
	 * 
	 * </ul>
	 * <p>
	 * (In the foregoing descriptions, a floating-point value is considered to
	 * be an integer if and only if it is a fixed point of the method
	 * {@link #ceil(double)} or, equivalently, a fixed point of the method
	 * {@link #floor(double)}. A value is a fixed point of a one-argument method
	 * if and only if the result of applying the method to the value is equal to
	 * the value.) This is accurate within 1 ulp, and is semi-monotonic.
	 * 
	 * @param a
	 *            the number to raise
	 * @param b
	 *            the power to raise it to
	 * @return a<sup>b</sup>
	 */
	public static double pow(double a, double b) {
		return VMNumber.pow(a, b);
	}

	/**
	 * Take the nearest integer that is that is greater than or equal to the
	 * argument. If the argument is NaN, infinite, or zero, the result is the
	 * same; if the argument is between -1 and 0, the result is negative zero.
	 * Note that <code>Math.ceil(x) == -Math.floor(-x)</code>.
	 * 
	 * @param a
	 *            the value to act upon
	 * @return the nearest integer &gt;= <code>a</code>
	 */
	public static double ceil(double a) {
		return VMNumber.ceil(a);
	}

	/**
	 * Take the nearest integer that is that is less than or equal to the
	 * argument. If the argument is NaN, infinite, or zero, the result is the
	 * same. Note that <code>Math.ceil(x) == -Math.floor(-x)</code>.
	 * 
	 * @param a
	 *            the value to act upon
	 * @return the nearest integer &lt;= <code>a</code>
	 */
	public static double floor(double a) {
		return VMNumber.floor(a);
	}

	/**
	 * Take the nearest integer to the argument. If it is exactly between two
	 * integers, the even integer is taken. If the argument is NaN, infinite, or
	 * zero, the result is the same.
	 * 
	 * @param a
	 *            the value to act upon
	 * @return the nearest integer to <code>a</code>
	 */
	public static double rint(double a) {
		return VMNumber.rint(a);
	}

	/**
	 * Take the nearest integer to the argument. This is equivalent to
	 * <code>(int) Math.floor(a + 0.5f)</code>. If the argument is NaN, the
	 * result is 0; otherwise if the argument is outside the range of int, the
	 * result will be Integer.MIN_VALUE or Integer.MAX_VALUE, as appropriate.
	 * 
	 * @param a
	 *            the argument to round
	 * @return the nearest integer to the argument
	 * @see Integer#MIN_VALUE
	 * @see Integer#MAX_VALUE
	 */
	public static int round(float a) {
		if (a != a)
			return 0;
		return (int) floor(a + 0.5f);
	}

	/**
	 * Take the nearest long to the argument. This is equivalent to
	 * <code>(long) Math.floor(a + 0.5)</code>. If the argument is NaN, the
	 * result is 0; otherwise if the argument is outside the range of long, the
	 * result will be Long.MIN_VALUE or Long.MAX_VALUE, as appropriate.
	 * 
	 * @param a
	 *            the argument to round
	 * @return the nearest long to the argument
	 * @see Long#MIN_VALUE
	 * @see Long#MAX_VALUE
	 */
	public static long round(double a) {
		if (a != a)
			return 0;
		return (long) floor(a + 0.5d);
	}

	/**
	 * Get a random number. This behaves like Random.nextDouble(), seeded by
	 * System.currentTimeMillis() when first called. In other words, the number
	 * is from a pseudorandom sequence, and lies in the range [+0.0, 1.0). This
	 * random sequence is only used by this method, and is threadsafe, although
	 * you may want your own random number generator if it is shared among
	 * threads.
	 * 
	 * @return a random number
	 * @see Random#nextDouble()
	 * @see System#currentTimeMillis()
	 */
	public static synchronized double random() {
		if (rand == null)
			rand = new Random();
		return rand.nextDouble();
	}

	/**
	 * Convert from degrees to radians. The formula for this is radians =
	 * degrees * (pi/180); however it is not always exact given the limitations
	 * of floating point numbers.
	 * 
	 * @param degrees
	 *            an angle in degrees
	 * @return the angle in radians
	 * @since 1.2
	 */
	public static double toRadians(double degrees) {
		return (degrees * PI) / 180;
	}

	/**
	 * Convert from radians to degrees. The formula for this is degrees =
	 * radians * (180/pi); however it is not always exact given the limitations
	 * of floating point numbers.
	 * 
	 * @param rads
	 *            an angle in radians
	 * @return the angle in degrees
	 * @since 1.2
	 */
	public static double toDegrees(double rads) {
		return (rads * 180) / PI;
	}

	/**
	 * <p>
	 * Take a cube root. If the argument is <code>NaN</code>, an infinity or
	 * zero, then the original value is returned. The returned result is within
	 * 1 ulp of the exact result. For a finite value, <code>x</code>, the cube
	 * root of <code>-x</code> is equal to the negation of the cube root of
	 * <code>x</code>.
	 * </p>
	 * <p>
	 * For a square root, use <code>sqrt</code>. For other roots, use
	 * <code>pow(a, 1 / rootNumber)</code>.
	 * </p>
	 * 
	 * @param a
	 *            the numeric argument
	 * @return the cube root of the argument
	 * @see #sqrt(double)
	 * @see #pow(double, double)
	 * @since 1.5
	 */
	public static double cbrt(double a) {
		return VMNumber.cbrt(a);
	}

	/**
	 * <p>
	 * Returns the hyperbolic cosine of the given value. For a value,
	 * <code>x</code>, the hyperbolic cosine is <code>(e<sup>x</sup> + 
	 * e<sup>-x</sup>)/2</code> with <code>e</code> being <a href="#E">Euler's
	 * number</a>. The returned result is within 2.5 ulps of the exact result.
	 * </p>
	 * <p>
	 * If the supplied value is <code>NaN</code>, then the original value is
	 * returned. For either infinity, positive infinity is returned. The
	 * hyperbolic cosine of zero is 1.0.
	 * </p>
	 * 
	 * @param a
	 *            the numeric argument
	 * @return the hyperbolic cosine of <code>a</code>.
	 * @since 1.5
	 */
	public static double cosh(double a) {
		return VMNumber.cosh(a);
	}

	/**
	 * <p>
	 * Returns the sign of the argument as follows:
	 * </p>
	 * <ul>
	 * <li>If <code>a</code> is greater than zero, the result is 1.0.</li>
	 * <li>If <code>a</code> is less than zero, the result is -1.0.</li>
	 * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>.
	 * <li>If <code>a</code> is positive or negative zero, the result is the
	 * same.</li>
	 * </ul>
	 * 
	 * @param a
	 *            the numeric argument.
	 * @return the sign of the argument.
	 * @since 1.5.
	 */
	public static double signum(double a) {
		if (Double.isNaN(a))
			return Double.NaN;
		if (a > 0)
			return 1.0;
		if (a < 0)
			return -1.0;
		return a;
	}

	/**
	 * <p>
	 * Returns the sign of the argument as follows:
	 * </p>
	 * <ul>
	 * <li>If <code>a</code> is greater than zero, the result is 1.0f.</li>
	 * <li>If <code>a</code> is less than zero, the result is -1.0f.</li>
	 * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>.
	 * <li>If <code>a</code> is positive or negative zero, the result is the
	 * same.</li>
	 * </ul>
	 * 
	 * @param a
	 *            the numeric argument.
	 * @return the sign of the argument.
	 * @since 1.5.
	 */
	public static float signum(float a) {
		if (Float.isNaN(a))
			return Float.NaN;
		if (a > 0)
			return 1.0f;
		if (a < 0)
			return -1.0f;
		return a;
	}

	/**
	 * <p>
	 * Returns the hyperbolic sine of the given value. For a value,
	 * <code>x</code>, the hyperbolic sine is <code>(e<sup>x</sup> - 
	 * e<sup>-x</sup>)/2</code> with <code>e</code> being <a href="#E">Euler's
	 * number</a>. The returned result is within 2.5 ulps of the exact result.
	 * </p>
	 * <p>
	 * If the supplied value is <code>NaN</code>, an infinity or a zero, then
	 * the original value is returned.
	 * </p>
	 * 
	 * @param a
	 *            the numeric argument
	 * @return the hyperbolic sine of <code>a</code>.
	 * @since 1.5
	 */
	public static double sinh(double a) {
		return VMNumber.sinh(a);
	}

	/**
	 * <p>
	 * Returns the hyperbolic tangent of the given value. For a value,
	 * <code>x</code>, the hyperbolic tangent is <code>(e<sup>x</sup> - 
	 * e<sup>-x</sup>)/(e<sup>x</sup> + e<sup>-x</sup>)</code> (i.e.
	 * <code>sinh(a)/cosh(a)</code>) with <code>e</code> being <a
	 * href="#E">Euler's number</a>. The returned result is within 2.5 ulps of
	 * the exact result. The absolute value of the exact result is always less
	 * than 1. Computed results are thus less than or equal to 1 for finite
	 * arguments, with results within half a ulp of either positive or negative
	 * 1 returning the appropriate limit value (i.e. as if the argument was an
	 * infinity).
	 * </p>
	 * <p>
	 * If the supplied value is <code>NaN</code> or zero, then the original
	 * value is returned. Positive infinity returns +1.0 and negative infinity
	 * returns -1.0.
	 * </p>
	 * 
	 * @param a
	 *            the numeric argument
	 * @return the hyperbolic tangent of <code>a</code>.
	 * @since 1.5
	 */
	public static double tanh(double a) {
		return VMNumber.tanh(a);
	}

	/**
	 * Return the ulp for the given double argument. The ulp is the difference
	 * between the argument and the next larger double. Note that the sign of
	 * the double argument is ignored, that is, ulp(x) == ulp(-x). If the
	 * argument is a NaN, then NaN is returned. If the argument is an infinity,
	 * then +Inf is returned. If the argument is zero (either positive or
	 * negative), then {@link Double#MIN_VALUE} is returned.
	 * 
	 * @param d
	 *            the double whose ulp should be returned
	 * @return the difference between the argument and the next larger double
	 * @since 1.5
	 */
	public static double ulp(double d) {
		if (Double.isNaN(d))
			return d;
		if (Double.isInfinite(d))
			return Double.POSITIVE_INFINITY;
		// This handles both +0.0 and -0.0.
		if (d == 0.0)
			return Double.MIN_VALUE;
		long bits = Double.doubleToLongBits(d);
		final int mantissaBits = 52;
		final int exponentBits = 11;
		final long expMask = (1L << exponentBits) - 1;
		long exponent = (bits >>> mantissaBits) & expMask;

		// Denormal number, so the answer is easy.
		if (exponent == 0) {
			long result = (exponent << mantissaBits) | 1L;
			return Double.longBitsToDouble(result);
		}

		// Conceptually we want to have '1' as the mantissa. Then we would
		// shift the mantissa over to make a normal number. If this underflows
		// the exponent, we will make a denormal result.
		long newExponent = exponent - mantissaBits;
		long newMantissa;
		if (newExponent > 0)
			newMantissa = 0;
		else {
			newMantissa = 1L << -(newExponent - 1);
			newExponent = 0;
		}
		return Double.longBitsToDouble((newExponent << mantissaBits)
				| newMantissa);
	}

	/**
	 * Return the ulp for the given float argument. The ulp is the difference
	 * between the argument and the next larger float. Note that the sign of the
	 * float argument is ignored, that is, ulp(x) == ulp(-x). If the argument is
	 * a NaN, then NaN is returned. If the argument is an infinity, then +Inf is
	 * returned. If the argument is zero (either positive or negative), then
	 * {@link Float#MIN_VALUE} is returned.
	 * 
	 * @param f
	 *            the float whose ulp should be returned
	 * @return the difference between the argument and the next larger float
	 * @since 1.5
	 */
	public static float ulp(float f) {
		if (Float.isNaN(f))
			return f;
		if (Float.isInfinite(f))
			return Float.POSITIVE_INFINITY;
		// This handles both +0.0 and -0.0.
		if (f == 0.0)
			return Float.MIN_VALUE;
		int bits = Float.floatToIntBits(f);
		final int mantissaBits = 23;
		final int exponentBits = 8;
		final int expMask = (1 << exponentBits) - 1;
		int exponent = (bits >>> mantissaBits) & expMask;

		// Denormal number, so the answer is easy.
		if (exponent == 0) {
			int result = (exponent << mantissaBits) | 1;
			return Float.intBitsToFloat(result);
		}

		// Conceptually we want to have '1' as the mantissa. Then we would
		// shift the mantissa over to make a normal number. If this underflows
		// the exponent, we will make a denormal result.
		int newExponent = exponent - mantissaBits;
		int newMantissa;
		if (newExponent > 0)
			newMantissa = 0;
		else {
			newMantissa = 1 << -(newExponent - 1);
			newExponent = 0;
		}
		return Float
				.intBitsToFloat((newExponent << mantissaBits) | newMantissa);
	}
}
